package mhcs.client;

import java.util.ArrayList;
import java.util.Iterator;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.IntegerBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;


class ConfigMap extends ScrollPanel implements MyListener {
    
    public ConfigMap() {
        MHCS.dataSet.addListener(this);
        xBox = new IntegerBox();
        yBox = new IntegerBox();
        flex = new FlexTable();

        popup1 = new PopupPanel(true);
        popupVertical = new VerticalPanel();
        popupVertical.add(new Label("Move Center of Gravity:"));
        popupVertical.add(new Label("X-coordinate:"));
        popupVertical.add(xBox);
        popupVertical.add(new Label("Y-coordinate:"));
        popupVertical.add(yBox);
        popupVertical.add(new Button("Move", new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                try {
                    centerX = xBox.getValue();
                    centerY = yBox.getValue();
                }
                catch (Exception e) {
                    PopupPanel pop = new PopupPanel(true);
                    pop.add(new Label("Center of gravity coordinates must be integers."));
                    pop.center();
                    pop.show();
                    
                }
                g.clear();
                markUnuseable();
                prevX = xSum/numModules - 1;
                prevY = ySum/numModules - 1;
                if (map == 1) {
                    mapOne();
                } else if (map == 2) {
                    mapTwo();
                } else if (map == 3) {
                    mapThree();
                } else if (map == 4) {
                    mapFour();
                }
            }
            
        }));
        popup1.add(popupVertical);
        move = new Button("Configuration Settings", new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                popup1.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
                    public void setPosition(int offsetWidth, int offsetHeight) {
                      int left = (Window.getClientWidth() - offsetWidth) / 3;
                      int top = (Window.getClientHeight() - offsetHeight) / 3;
                      popup1.setPopupPosition(left, top);
                    }
                  });
            }
            
        });

        popup2 = new PopupPanel(true);
        noMin = new String("Quality: 0/100" + "<br>"
                + "No minimum available for this configuration.");
        airlockSides = new String("Airlocks should be located on all" 
                + " sides of the Habitat.");
        dormWings = new String("Dormitory modules should be located in"
                + " recognisable dormitory wings of the Habitat.");
        gymSani = new String("A Gym & Relaxation module should"
                + " be next to a Sanitation module.");
        medAirlock = new String("One Medical module should be"
                + " next to one Airlock module.");
        foodCanteen = new String("Food & Water storage modules"
                + " should be located near Canteen modules.");
        dormSani = new String("Dormitory wings should have Sanitation modules"
                + " in the ratio of 1 Sanitation module for every 2 Dormitory modules.");
        specialDistributed = new String("Special module types (types for which there"
                + " are only 4 modules e.g. Medical) should be located<br>"
                + "throughout the Habitat and not located altogether in one part.");
        qualityHTML = new HTML("Total Moving Task: " + Integer.toString(movingTask)
                + "m" + "<br>" + noMin);
        popup2.add(qualityHTML);
        quality = new Button("Configuration Quality", new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                popup2.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
                    public void setPosition(int offsetWidth, int offsetHeight) {
                      int left = (Window.getClientWidth() - offsetWidth) / 3;
                      int top = (Window.getClientHeight() - offsetHeight) / 3;
                      popup2.setPopupPosition(left, top);
                    }
                  });
            }
            
        });
        
        g = new Grid(50, 100);
        g.setCellPadding(0);
        g.setCellSpacing(0);
        HorizontalPanel hp = new HorizontalPanel();
        hp.add(move);
        hp.add(quality);
        flex.setWidget(0, 0, hp);
        flex.setWidget(1, 0, g);
        add(flex);
        for (int row = 0; row < 50; row++) {
            for (int col = 0; col < 100; col++) {
                g.getCellFormatter().setStyleName(row, col, "g");
            }
        }
        g.setStyleName("myGrid");
        
        markUnuseable();
        
        plain = new ArrayList<ConfigImage>();
        canteen = new ArrayList<ConfigImage>();
        airlock = new ArrayList<ConfigImage>();
        dormitory = new ArrayList<ConfigImage>();
        sanitation = new ArrayList<ConfigImage>();
        gym = new ArrayList<ConfigImage>();
        control = new ArrayList<ConfigImage>();
        power = new ArrayList<ConfigImage>();
        medical = new ArrayList<ConfigImage>();
        food = new ArrayList<ConfigImage>();
        
        xIndex = 25;
        yIndex = 10;
        xSum = 0;
        ySum = 0;
        numModules = 0;
        map = 0;
        height = 0;
        width = 0;
        movingTask = 0;
        qual = 0;
        hasMin = false;
    }
    
    @Override
    public void actionPerformed(final String action, final Module module) {
        if (action.equals("clear")) {
            plain = new ArrayList<ConfigImage>();
            canteen = new ArrayList<ConfigImage>();
            airlock = new ArrayList<ConfigImage>();
            dormitory = new ArrayList<ConfigImage>();
            sanitation = new ArrayList<ConfigImage>();
            gym = new ArrayList<ConfigImage>();
            control = new ArrayList<ConfigImage>();
            power = new ArrayList<ConfigImage>();
            medical = new ArrayList<ConfigImage>();
            food = new ArrayList<ConfigImage>();
            qualityHTML.setHTML("Total Moving Task: 0m" + "<br>" + noMin);
            
            xIndex = 25;
            yIndex = 10;
            xSum = 0;
            ySum = 0;
            numModules = 0;
            map = 0;
            height = 0;
            width = 0;
            movingTask = 0;
            qual = 0;
            hasMin = false;
        }
        if (action.equals("add")) {
            numModules++;
            xSum += module.getX();
            ySum += module.getY();
            if (module.getType().equals("Plain")) {
                ConfigImage image = new ConfigImage("images/Plain.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                plain.add(image);
            }else if (module.getType().equals("Canteen")) {
                ConfigImage image = new ConfigImage("images/Canteen.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                canteen.add(image);
            }else if (module.getType().equals("Airlock")) {
                ConfigImage image = new ConfigImage("images/Airlock.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                airlock.add(image);
            }else if (module.getType().equals("Food")) {
                ConfigImage image = new ConfigImage("images/Food.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                food.add(image);
            }else if (module.getType().equals("Medical")) {
                ConfigImage image = new ConfigImage("images/Medical.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                medical.add(image);
            }else if (module.getType().equals("Sanitation")) {
                ConfigImage image = new ConfigImage("images/Sanitation.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                sanitation.add(image);
            }else if (module.getType().equals("Gym")) {
                ConfigImage image = new ConfigImage("images/Gym.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                gym.add(image);
            }else if (module.getType().equals("Power")) {
                ConfigImage image = new ConfigImage("images/Power.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                power.add(image);
            }else if (module.getType().equals("Control")) {
                ConfigImage image = new ConfigImage("images/Control.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                control.add(image);
            }else if (module.getType().equals("Dormitory")) {
                ConfigImage image = new ConfigImage("images/Dormitory.jpg", module.getSerial(),
                        module.getX(), module.getY());
                 
                dormitory.add(image);
            }
            if (plain.size() >= 3 && control.size() >= 1 && power.size() >= 1
                    && dormitory.size() >= 1 && food.size() >= 1
                    && sanitation.size() >= 1 && canteen.size() >= 1
                    && airlock.size() >= 1 && !hasMin) {
                //Window.alert("Minimum Configuration Available");
                PopupPanel alert = new PopupPanel();
                alert.center();
                alert.add(new Label("Minimum Configuration Available"));
                alert.show();
                alert.setAutoHideEnabled(true);
                hasMin = true;
            }
        }
        if (action.equals("remove")) {
            numModules--;
            xSum -= module.getX();
            ySum -= module.getY();
            Iterator<ConfigImage> iter;
            if (module.getType().equals("Plain")) {
                iter = plain.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (module.getType().equals("Gym")) {
                iter = gym.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (module.getType().equals("Food")) {
                iter = food.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (module.getType().equals("Canteen")) {
                iter = canteen.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (module.getType().equals("Sanitation")) {
                iter = sanitation.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (module.getType().equals("Airlock")) {
                iter = airlock.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (module.getType().equals("Medical")) {
                iter = medical.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (module.getType().equals("Power")) {
                iter = power.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (module.getType().equals("Control")) {
                iter = control.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (module.getType().equals("Dormitory")) {
                iter = dormitory.iterator();
                while (iter.hasNext()) {
                    
                    if (iter.next().getSerial() == module.getSerial()) {
                        iter.remove();
                    }
                }
            }
            if (plain.size() < 3 || control.size() < 1 || power.size() < 1
                    || dormitory.size() < 1 || food.size() < 1
                    || sanitation.size() < 1 || canteen.size() < 1
                    || airlock.size() < 1) {
                if (hasMin) {
                    //Window.alert("Minimum Configuration no longer available.");
                	PopupPanel alert = new PopupPanel();
                    alert.center();
                    alert.add(new Label("Minimum Configuration no longer available."));
                    alert.show();
                    alert.setAutoHideEnabled(true);
                    hasMin = false;
                }
            }
        }
        if (action.equals("set")) {
            g.clear();
            markUnuseable();
            centerX = xSum/numModules - 1;
            centerY = ySum/numModules - 1;
            prevX = centerX;
            prevY = centerY;
            map = module.getSerial();
            if (map == 1) {
                mapOne();
            }else if (map == 2) {
                mapTwo();
            } else if (map == 3) {
                mapThree();
            } else if (map == 4) {
                mapFour();
            }
        }
    }
    
    private void mapOne() {
        height = 3;
        width = 5;
        setIndices();
        setW(49 - yIndex, xIndex + 1, power.get(0));
        setW(49 - yIndex, xIndex + 2, control.get(0));
        setW(49 - yIndex, xIndex + 3, dormitory.get(0));
        setW(49 - (yIndex + 1), xIndex, food.get(0));
        setW(49 - (yIndex + 1), xIndex + 1, plain.get(0));
        setW(49 - (yIndex + 1), xIndex + 2, plain.get(1));
        setW(49 - (yIndex + 1), xIndex + 3, plain.get(2));
        setW(49 - (yIndex + 1), xIndex + 4, sanitation.get(0));
        setW(49 - (yIndex + 2), xIndex + 1, canteen.get(0));
        setW(49 - (yIndex + 2), xIndex + 3, airlock.get(0));
        qualityHTML.setHTML("Total Moving Task: " + Integer.toString(movingTask) + "m"
                + "<br>" + "Quality: 25/100<br>Minimum configurations violate these"
                + " rules:<br>" + airlockSides + "<br>" + dormWings + "<br>"
                + gymSani + "<br>" + medAirlock);
    }
    
    private void mapTwo() {
        height = 4;
        width = 4;
        setIndices();
        setW(49 - yIndex, xIndex + 1, control.get(0));
        setW(49 - yIndex, xIndex + 2, power.get(0));
        setW(49 - (yIndex + 1), xIndex, airlock.get(0));
        setW(49 - (yIndex + 1), xIndex + 1, plain.get(0));
        setW(49 - (yIndex + 1), xIndex + 2, plain.get(1));
        setW(49 - (yIndex + 1), xIndex + 3, food.get(0));
        setW(49 - (yIndex + 2), xIndex, sanitation.get(0));
        setW(49 - (yIndex + 2), xIndex + 1, plain.get(2));
        setW(49 - (yIndex + 2), xIndex + 2, canteen.get(0));
        setW(49 - (yIndex + 3), xIndex + 1, dormitory.get(0));
        qualityHTML.setHTML("Total Moving Task: " + Integer.toString(movingTask) + "m"
                + "<br>" + "Quality: 25/100<br>Minimum configurations violate these"
                + " rules:<br>" + airlockSides + "<br>" + dormWings + "<br>"
                + gymSani + "<br>" + medAirlock);
    }
    private void mapThree() {
        int yOffset = 0;
        height = 3;
        int plainSize = plain.size();
        width = plainSize + 1;
        int foodSize = food.size();
        
        if (plainSize > 30) {
            height = plainSize - 19;
            width = 21;
            if (foodSize >= 8) {
                width++;
            }
            if (foodSize >= 10 && plainSize >= 40) {
                height++;
            }
            yOffset = 9;
            if (foodSize >= 5) {
                height++;
                yOffset++;
            }
        } else if (plainSize > 20) {
            height = 12;
            yOffset = 9;
            if (foodSize >= 5) {
                height++;
                yOffset++;
            }
            width = plainSize - 20;
            if (foodSize >= 8 && plainSize == 30) {
                width++;
            }
        } else if (plainSize > 10) {
            height = plainSize - 8;
            width = 11;
            yOffset = plainSize - 11;
            if (plainSize == 20 && foodSize >= 5) {
                height++;
            }
            if (medical.size() < 1 || gym.size() < 1 || control.size() < 1
                    || power.size() > 1 || sanitation.size() > 3
                    || airlock.size() > 1) {
                width++;
            }
        }
        
        setIndices();
        
        plit = plain.iterator();
        doit = dormitory.iterator();
        gyit = gym.iterator();
        meit = medical.iterator();
        foit = food.iterator();
        aiit = airlock.iterator();
        cait = canteen.iterator();
        poit = power.iterator();
        coit = control.iterator();
        sait = sanitation.iterator();
        
        buildThreeWest(yOffset);
        if (plit.hasNext()) {
            buildThreeSouth(yOffset);
        }
        if (plit.hasNext()) {
            buildThreeEast(yOffset);
        }
        if (plit.hasNext()) {
            buildThreeNorth(yOffset);
        }
        String qualityText = new String(dormWings);
        int qualReport = 100;
        if (plain.size() < 7 || !hasMin) {
            qualityText = "Total Moving Task: " + Integer.toString(movingTask) + "m"
                    + "<br>" + noMin;
        } else {
            int reduction = 15 - qual/10;
            qual = 100;
            if (plain.size() < 40 || airlock.size() < 4) {
                qual -= reduction;
                qualityText += "<br>" + airlockSides;
            }
            if (gym.size() < 1) {
                qual -= reduction/2;
                qualityText += "<br>" + gymSani;
            }
            if (medical.size() < 1) {
                qual -= reduction;
                qualityText += "<br>" + medAirlock;
            }
            if (plain.size() == 19 && food.size() > 3) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            } else if (plain.size() > 19 && food.size() > 3 && canteen.size() < 2) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            } else if (plain.size() >= 28 && plain.size() <= 29 && food.size() > 5) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            } else if (plain.size() > 29 && food.size() > 5 && canteen.size() < 3) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            } else if (plain.size() == 39 && food.size() > 8) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            } else if (plain.size() > 39 && food.size() > 8 && canteen.size() < 4) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            }
            if (plain.size() > 4 && dormitory.size() > 2 && sanitation.size() < 2) {
                qual -= reduction;
                qualityText += "<br>" + dormSani;
            } else if (plain.size() > 6 && dormitory.size() > 4) {
                qual -= reduction;
                qualityText += "<br>" + dormSani;
            }
            qualityText = "Total Moving Task: " + Integer.toString(movingTask)
                    + "m" + "<br>" + "Quality: " + Integer.toString(qual) + "/"
                    + Integer.toString(qualReport) + "<br>" + qualityText;
        }
        qualityHTML.setHTML(qualityText);
    }
    
    private void buildThreeWest(int yOffset) {
        for (int i = 1; i <= 10 && plit.hasNext(); i++) {
            setW(49 - (yIndex + yOffset + 1), xIndex + i, plit.next());
            if (i == 1) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 1), xIndex, foit.next());
                }
                if (cait.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + 1, cait.next());
                }
                if (aiit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + 1, aiit.next());
                }
            }
            if (i == 2) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + 2, foit.next());
                }
                if (meit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + 2, meit.next());
                }
            }
            if (i == 3) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + 3, foit.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + 3, sait.next());
                }
            }
            if (i == 4) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, doit.next());
                }
                if (gyit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + 4, gyit.next());
                }
            }
            if (i == 5) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, doit.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + 5, sait.next());
                }
            }
            if (i == 6) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, doit.next());
                }
                if (coit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + 6, coit.next());
                }
            }
            if (i == 7) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, doit.next());
                }
                if (poit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + 7, poit.next());
                }
            }
            if (i == 8) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + 8, doit.next());
                }
            }
        }
    }
    
    private void buildThreeSouth(int yOffset) {
        for (int i = 0; i < 10 && plit.hasNext(); i++) {
            setW(49 - (yIndex + yOffset - i), xIndex + 10, plit.next());
            if (i == 2) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset - i), xIndex + 9, sait.next());
                }
            }
            if (i == 3) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset - i), xIndex + 9, doit.next());
                }
                if (coit.hasNext()) {
                    setW(49 - (yIndex + yOffset - 3), xIndex + 11, coit.next());
                }
            }
            if (i == 4) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset - i), xIndex + 9, doit.next());
                }
                if (poit.hasNext()) {
                    setW(49 - (yIndex + yOffset - 4), xIndex + 11, poit.next());
                }
            }
            if (i == 5) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset - i), xIndex + 9, doit.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset - 5), xIndex + 11, sait.next());
                }
            }
            if (i == 6) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset - i), xIndex + 9, doit.next());
                }
                if (gyit.hasNext()) {
                    setW(49 - (yIndex + yOffset - 6), xIndex + 11, gyit.next());
                }
            }
            if (i == 7) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset - i), xIndex + 9, doit.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset - 7), xIndex + 11, sait.next());
                }
            }
            if (i == 8) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex + yOffset - i), xIndex + 9, foit.next());
                }
                if (meit.hasNext()) {
                    setW(49 - (yIndex + yOffset - 8), xIndex + 11, meit.next());
                }
            }
            if (i == 9) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex + yOffset - 10), xIndex + 10, foit.next());
                }
                if (cait.hasNext()) {
                    setW(49 - (yIndex + yOffset - i), xIndex + 9, cait.next());
                }
                if (aiit.hasNext()) {
                    setW(49 - (yIndex + yOffset - i), xIndex + 11, aiit.next());
                }
            }
        }
    }
    
    private void buildThreeEast(int yOffset) {
        for (int i = 11; i <= 20 && plit.hasNext(); i++) {
            setW(49 - (yIndex + yOffset + 1), xIndex + i, plit.next());
            if (i == 13) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + i, doit.next());
                }
            }
            if (i == 14) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + i, doit.next());
                }
                if (coit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, coit.next());
                }
            }
            if (i == 15) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + i, doit.next());
                }
                if (poit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, poit.next());
                }
            }
            if (i == 16) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + i, doit.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, sait.next());
                }
            }
            if (i == 17) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + i, doit.next());
                }
                if (gyit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, gyit.next());
                }
            }
            if (i == 18) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + i, doit.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, sait.next());
                }
            }
            if (i == 19) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + i, doit.next());
                }
                if (meit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, meit.next());
                }
            }
            if (i == 20) {
                if (cait.hasNext()) {
                    setW(49 - (yIndex + yOffset), xIndex + i, cait.next());
                }
                if (aiit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 2), xIndex + i, aiit.next());
                }
                if (foit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 1),
                            xIndex + 1 + i, foit.next());
                }
            }
            
        }
    }
    
    private void buildThreeNorth(int yOffset) {
        for (int i = 2; i < 12 && plit.hasNext(); i++) {
            setW(49 - (yIndex + yOffset + i), xIndex + 11, plit.next());
            if (i == 4) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 12, sait.next());
                }
            }
            if (i == 5) {
                if (coit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 10, coit.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 12, doit.next());
                }
            }
            if (i == 6) {
                if (poit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 10, poit.next());
                }if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 12, doit.next());
                }
            }
            if (i == 7) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 10, sait.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 12, doit.next());
                }
            }
            if (i == 8) {
                if (gyit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 10, gyit.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 12, doit.next());
                }
            }
            if (i == 9) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 10, sait.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 12, doit.next());
                }
            }
            if (i == 10) {
                if (meit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 10, meit.next());
                }
                if (foit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 12, foit.next());
                }
            }
            if (i == 11) {
                if (aiit.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 10, aiit.next());
                }
                if (cait.hasNext()) {
                    setW(49 - (yIndex + yOffset + i),
                            xIndex + 12, cait.next());
                }
                if (foit.hasNext()) {
                    setW(49 - (yIndex + yOffset + 1 + i),
                            xIndex + 11, foit.next());
                }
            }
        }
    }
    
    private void mapFour() {
        int plainSize = plain.size();
        height = plainSize + 2;
        width = 2;
        if (dormitory.size() > 1) {
            width++;
        }
        if (plainSize >= 30) {
            height = 13;
            width = 21;
            if (sanitation.size() > 5 || dormitory.size() > 12
                    || gym.size() > 3) {
                width++;
            }
        } else if (plainSize > 11) {
            height = 13;
            width = plainSize - 9;
        } else if (plainSize >= 10) {
            height++;
        }
        
        setIndices();
        
        plit = plain.iterator();
        doit = dormitory.iterator();
        gyit = gym.iterator();
        meit = medical.iterator();
        foit = food.iterator();
        aiit = airlock.iterator();
        cait = canteen.iterator();
        poit = power.iterator();
        coit = control.iterator();
        sait = sanitation.iterator();
        buildFourLeft();
        if (plit.hasNext()) {
            buildFourCorridor();
        }
        if (plit.hasNext()) {
            buildFourRight();
        }
        String qualityText = new String("");
        if (plain.size() < 13 || !hasMin) {
            qualityText = "Total Moving Task: " + Integer.toString(movingTask) + "m"
                    + "<br>" + noMin;
        } else {
            int reduction = 15 - qual/10;
            int qualReport = 100;
            qual = 100;
            if (airlock.size() < 4 || plain.size() < 40) {
                qual -= reduction;
                qualityText += "<br>" + airlockSides;
            }
            if (gym.size() < 1 || dormitory.size() < 9) {
                qual -= reduction/2;
                qualityText += "<br>" + gymSani;
            }
            if (medical.size() < 1) {
                qual -= reduction;
                qualityText += "<br>" + medAirlock;
            }
            if (plain.size() == 20 && food.size() > 3) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            } else if (plain.size() > 20 && food.size() > 3 && canteen.size() < 3) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            } else if (plain.size() > 24 && plain.size() < 28 && food.size() > 5) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            } else if (plain.size() > 27 && food.size() > 5 && canteen.size() < 4) {
                qual -= reduction/2;
                qualityText += "<br>" + foodCanteen;
            }
            if (dormitory.size() < 11 && dormitory.size() > sanitation.size() * 2) {
                qual -= reduction;
                qualityText += "<br>" + dormSani;
            } else if (plain.size() == 29 && dormitory.size() > 10) {
                qual -= reduction;
                qualityText += "<br>" + dormSani;
            } else if (plain.size() == 30 && dormitory.size() > sanitation.size() * 2) {
                qual -= reduction;
                qualityText += "<br>" + dormSani;
            } else if (plain.size() > 30 && plain.size() < 35 && dormitory.size() > 12) {
                qual -= reduction;
                qualityText += "<br>" + dormSani;
            } else if (plain.size() == 35) {
                if (dormitory.size() > 16) {
                    qual -= reduction;
                    qualityText += "<br>" + dormSani;
                } else if (dormitory.size() > sanitation.size() * 2) {
                    qual -= reduction;
                    qualityText += "<br>" + dormSani;
                }
            } else if (plain.size() == 36 &&dormitory.size() > sanitation.size() * 2) {
                qual -= reduction;
                qualityText += "<br>" + dormSani;
            } else if (plain.size() == 37) {
                if (dormitory.size() > 18 || dormitory.size() > sanitation.size() * 2) {
                    qual -= reduction;
                    qualityText += "<br>" + dormSani;
                } else if (dormitory.size() > sanitation.size()) {
                    qual -= reduction;
                    qualityText += "<br>" + dormSani;
                }
            } else if (plain.size() > 37 && dormitory.size() > sanitation.size() * 2) {
                qual -= reduction;
                qualityText += "<br>" + dormSani;
            }
            qualityText ="Total Moving Task: " + Integer.toString(movingTask)
                    + "m" + "<br>" +  "Quality: " + Integer.toString(qual) + "/"
            + Integer.toString(qualReport) + qualityText;
        }
        qualityHTML.setHTML(qualityText);
    }
    
    private void buildFourLeft() {
        for (int i = 2; i < 12 && plit.hasNext(); i++) {
            setW(49 - (yIndex+ i), xIndex + 1, plit.next());
            if (i == 2) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex+ i), xIndex, doit.next());
                }
            }
            if (i == 3) {
                if (gyit.hasNext()) {
                    setW(49 - (yIndex+ i), xIndex, gyit.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 2, doit.next());
                }
            }
            if (i == 4) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + i), xIndex, sait.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 2, sait.next());
                }
            }
            if (i == 5) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex, doit.next());
                }
                if (coit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 2, coit.next());
                }
            }
            if (i == 6) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex, doit.next());
                }
                if (poit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 2, poit.next());
                }
            }
            if (i == 7) {
                if (gyit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex, gyit.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 2, doit.next());
                }
            }
            if (i == 8) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + i), xIndex, sait.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 2, sait.next());
                }
            }
            if (i == 9) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex, doit.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 2, doit.next());
                }
            }
            if (i == 10) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex, doit.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 2, doit.next());
                }
            }
            if (i == 11) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + i), xIndex, sait.next());
                }
                if (aiit.hasNext()) {
                    setW(49 - (yIndex + i + 1), xIndex + 1, aiit.next());
                }
                if (meit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 2, meit.next());
                }
            }
        }
    }
    
    private void buildFourCorridor() {
        for (int i = 1; i < 21 && plit.hasNext(); i++) {
            setW(49 - (yIndex + 1), xIndex + i, plit.next());
            if (i == 1) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + 1), xIndex, doit.next());
                }
            }
            if (i == 2) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, foit.next());
                }
            }
            if (i == 3) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, foit.next());
                }
                if (cait.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, cait.next());
                }
            }
            if (i == 4) {
                if (cait.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, cait.next());
                }
                if (foit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, foit.next());
                }
            }
            if (i == 5) {
                if (poit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, poit.next());
                }
                if (coit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, coit.next());
                }
            }
            if (i == 8) {
                if (meit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, meit.next());
                }
            }
            if (i == 9) {
                if (aiit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, aiit.next());
                }
                if (aiit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, aiit.next());
                }
            }
            if (i == 10) {
                if (meit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, meit.next());
                }
                if (foit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, foit.next());
                }
            }
            if (i == 11) {
                if (cait.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, cait.next());
                }
            }
            if (i == 12) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, foit.next());
                }
            }
            if (i == 13) {
                if (poit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, poit.next());
                }
                if (coit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, coit.next());
                }
            }
            if (i == 15) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, foit.next());
                }
            }

            if (i == 16) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, foit.next());
                }
                if (foit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, foit.next());
                }
            }

            if (i == 17) {
                if (foit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, foit.next());
                }
                if (foit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, foit.next());
                }
            }
            if (i == 18) {
                if (gyit.hasNext()) {
                    setW(49 - (yIndex + 2), xIndex + i, gyit.next());
                }
                if (cait.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, cait.next());
                }
            }
            if (i == 19) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, doit.next());
                }
            }
            if (i == 20) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex), xIndex + i, doit.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + 1), xIndex + 1 + i, sait.next());
                }
            }
        }
    }
    
    private void buildFourRight() {
        for (int i = 2; i < 12 && plit.hasNext(); i++) {
            setW(49 - (yIndex + i), xIndex + 20, plit.next());
            if (i == 2) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 21, doit.next());
                }
            }
            if (i == 3) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 19, doit.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 21, doit.next());
                }
            }
            if (i == 4) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 19, doit.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 21, doit.next());
                }
            }
            if (i == 5) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 19, sait.next());
                }
                if (sait.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 21, sait.next());
                }
            }
            if (i == 6) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 19, sait.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 21, doit.next());
                }
            }
            if (i == 7) {
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 19, doit.next());
                }
                if (doit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 21, doit.next());
                }
            }
            if (i == 8) {
                if (sait.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 19, sait.next());
                }
                if (gyit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 21, gyit.next());
                }
            }
            if (i == 9) {
                if (coit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 19, coit.next());
                }
            }
            if (i == 10) {
                if (poit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 19, poit.next());
                }
            }
            if (i == 11) {
                if (meit.hasNext()) {
                    setW(49 - (yIndex + i), xIndex + 19, meit.next());
                }
                if (aiit.hasNext()) {
                    setW(49 - (yIndex + i + 1), xIndex + 20, aiit.next());
                }
            }
        }
    }
    
    private void setIndices() {
        movingTask = 0;
        xIndex = centerX - width/2 - 1;
        yIndex = centerY - height/2 - 1;
        qual = 0;
        if (xIndex < 0) {
            xIndex = 0;
        } else if (xIndex > 100 - width) {
            xIndex = 100 - width;
        }
        if (yIndex < 0) {
            yIndex = 0;
        } else if (yIndex > 50 - height) {
            yIndex = 50 - height;
        }
        if (xIndex > 39 - width && xIndex < 50 && yIndex > 39 - height) {
            if (xIndex < 45) {
                if (xIndex > yIndex) {
                    yIndex = 39 - height;
                } else {
                    xIndex = 39 - width;
                }
            } else if (90 - xIndex > yIndex) {
                yIndex = 39 - height;
            }
            else {
                xIndex = 50;
            }
        }
    }
    
    private void markUnuseable() {
        for (int row = 0; row < 11; row++) {
            for (int col = 39; col < 50; col++) {
                Image image = new Image("images/Area.jpg");
                image.setPixelSize(20, 20);
                g.setWidget(row, col, image);
            }
        }
    }
    
    private void setW(int why, int ex, ConfigImage image) {
        g.setWidget(why, ex, image.getImage());
        qual++;
        movingTask += (Math.abs((image.getY() -1)- prevY)
                + Math.abs((image.getX() -1) - prevX))*5;
        movingTask += (Math.abs(why - image.getY()) + Math.abs(ex - image.getX()))*5;
        prevY = why;
        prevX = ex;
    }
    
    private Grid g;
    
    private ArrayList<ConfigImage> plain;
    private ArrayList<ConfigImage> canteen;
    private ArrayList<ConfigImage> airlock;
    private ArrayList<ConfigImage> food;
    private ArrayList<ConfigImage> medical;
    private ArrayList<ConfigImage> power;
    private ArrayList<ConfigImage> control;
    private ArrayList<ConfigImage> gym;
    private ArrayList<ConfigImage> sanitation;
    private ArrayList<ConfigImage> dormitory;

    Iterator<ConfigImage> plit;
    Iterator<ConfigImage> doit;
    Iterator<ConfigImage> gyit;
    Iterator<ConfigImage> meit;
    Iterator<ConfigImage> foit;
    Iterator<ConfigImage> aiit;
    Iterator<ConfigImage> cait;
    Iterator<ConfigImage> poit;
    Iterator<ConfigImage> coit;
    Iterator<ConfigImage> sait;
    
    private String noMin;
    private String airlockSides;
    private String dormWings;
    private String gymSani;
    private String medAirlock;
    private String foodCanteen;
    private String dormSani;
    private String specialDistributed;
    
    private int xIndex;
    private int yIndex;
    private int centerX;
    private int centerY;
    private int map;
    private int height;
    private int width;
    private int xSum;
    private int ySum;
    private int numModules;
    private int movingTask;
    private int prevX;
    private int prevY;
    private int qual;
    private boolean hasMin;
    private Button move;
    private Button quality;
    private PopupPanel popup1;
    private PopupPanel popup2;
    private HTML qualityHTML;
    private FlexTable flex;
    private VerticalPanel popupVertical;
    private IntegerBox xBox;
    private IntegerBox yBox;
}